鐵人賽
單執行緒的意思就是一次只能處理一件事情,怎麼會有執行程式不阻塞的可能?
這時就會介紹到 Event Loop 這個非同步概念裡的重要角色。
Event Loop示意圖
就如上圖 JS 裡的 stack 的執行程序確實只能一次執行一個,當遇到非同步的執行任務如 setTimeout 就會使用 請 WebAPI 設定計時,等到計時結束
callback function 會排到 callback queue 裡面依續排隊。
Event Loop 的功用非常的簡單,當今天 stack 上面沒有任何執行任務,
就把 callback queue 最先排隊的任務傳到 stack 執行。
這個機制也解釋了為什麼 setTimeout 的時間參數即使設定為 0 毫秒也不會立即執行 callback function 。
console.log('start');
(function(){
console.log('apply function')
window.setTimeout(function(){
console.log('pick me first');
},0)
})()
console.log('end');
// cosole 結果
"start"
"apply function"
"end"
"pick me first"
閉包的概念可以理解成讓變數鎖在特定的作用域裡面,只有 function 內部可以使用,就像是物件有 private 方法。
不使用閉包的狀況雖然可以使用全域變數,但會造成變數污染,兩個 function 都用到相同的變數產生預期外的 bug。
只有一組 function 的情況
var count = 0
function countSheep(){
count +=1;
console.log(count+'sheep');
}
countSheep();
countSheep();
countSheep();
//1sheep
//2sheep
//3sheep
使用兩組 function 後變數污染
var count = 0
function countSheep(){
count +=1;
console.log(count+'sheep');
}
countSheep();
countSheep();
countSheep();
function countCat(){
count +=1;
console.log(count+'cat');
}
countCat();
countCat();
countCat();
countSheep();
// 輸出結果
"1sheep"
"2sheep"
"3sheep"
"4cat"
"5cat"
"6cat"
"7sheep"
應家要有兩個獨立的計數器,因為使用全域變數而混在一起了。
使用閉包的情況
function farm(){
var count = 0;
function countSheep(){
count+=1;
console.log(count+'sheep');
}
return countSheep;
}
const countSheep = farm()
countSheep();
countSheep();
// 輸出結果
"1sheep"
"2sheep"
透過外層 function 回傳內層 function的方式,可以取得當時定義 function 內的變數,記住當時的環境變數就是閉包。
補充
由於外層 function 回傳另一個在內部的 function,所以透過指定給變數再呼叫內部 function 本身才會取得我們要的值。
function farm(){
var count = 0;
function countSheep(){
count+=1;
console.log(count+'sheep');
}
return countSheep;
}
const countSheep = farm()
console.log(countSheep);
// 輸出結果
function countSheep(){
count+=1;
window.runnerWindow.proxyConsole.log(count+'sheep');
}